Schema (effect)
docs
#wip
Decoding
外部からの入力(JSONなど)を TypeScript の型に変換
Encoding
TypeScript の値を外部形式(例:文字列)に変換
Asserting
値が指定されたスキーマに準拠しているかチェック
Schema生成
JSON Schema を自動で生成
Standard Schemaも生成
Pretty Printing
データの見やすい表示
Arbitrary生成
テストのためにランダムなデータを生成(fast-check 向け)
Schema<Type, Encoded, Requirements>
Type
出力
decode 後の型
Encoded
入力
encode 前の型
Requirements
decode/encode 時に必要なContext (Effect)
code:_
┌─────────┐ ┌───┐ ┌───┐ ┌─────────┐
| unknown | | A | | I | | unknown |
└─────────┘ └───┘ └───┘ └─────────┘
| | | |
| validate | | |
|─────────────►│ | |
| | | |
| is | | |
|─────────────►│ | |
| | | |
| asserts | | |
|─────────────►│ | |
| | | |
| encodeUnknown| | |
|─────────────────────────►| |
| | |
| encode | |
|──────────►│ |
| | |
| decode | |
| ◄─────────| |
| | |
| | decodeUnknown|
| ◄────────────────────────|
code:ts
import { Schema } from "effect"
// 定義
const Person = Schema.Struct({
name: Schema.String,
age: Schema.Number
})
型の取得
3種類の方法がある
code:ts
type Person1 = typeof Person.Type
type Person2 = Schema.Schema.Type<typeof Person>
interface Person3 extends Schema.Schema.Type<typeof Person> {}
1でええやんmrsekut.icon
何のために2番目あるんや
3番目は読みやすさとパフォーマンスが良いと書いているが、どこが読みやすいのかわからん
入力の型も得られる
.Encoded
code:ts
type Person_ = typeof Person.Encoded
Contextの型
code:ts
type PersonContext = typeof Person.Context
Opaque Typeを定義できる
型の内部構造を隠蔽した型
code:ts
const _Person = Schema.Struct({
name: Schema.String,
age: Schema.Number
})
// Declare the type interface to make it opaque
interface Person extends Schema.Schema.Type<typeof _Person> {}
// Re-declare the schema as opaque
const Person: Schema.Schema<Person> = _Person
Schema.Schema.Type
https://effect.website/docs/schema/getting-started/#schemas-with-opaque-types
https://effect.website/docs/schema/classes/
decode
Schema.decodeUnknownSync
失敗したらthrow error
code:ts
Schema.decodeUnknownSync(Person)(input)
カリー化されてるんやmrsekut.icon
Schema.decodeUnknownOption
Option型を返す
Schema.decodeUnknownEither
Either型を返す
Schema.decodeUnknownPromise
decodeしてPromiseを返す
なぜ?mrsekut.icon
code:ts
const asyncSchema = Schema.transformOrFail(PersonId, Person, {
strict: true,
// Decode with simulated async transformation
decode: (id) =>
Effect.succeed({ id, name: "name", age: 18 }).pipe(
Effect.delay("10 millis")
),
encode: (person) =>
Effect.succeed(person.id).pipe(Effect.delay("10 millis"))
})
Effect.runPromise(Schema.decodeUnknown(asyncSchema)(1)).then(console.log)
非同期な変換が含まれるSchemaというのがあるらしい
Schema.transformOrFail
Schema.decodeUnknown
decodeしてEffectを返す
exact
https://effect.website/docs/schema/getting-started/#managing-missing-properties
デフォルト
code:ts
import { Schema } from "effect"
const schema = Schema.Struct({ a: Schema.Unknown })
const input = {}
console.log(Schema.decodeUnknownSync(schema)(input))
// Output: { a: undefined }
exact: true
code:ts
import { Schema } from "effect"
const schema = Schema.Struct({ a: Schema.Unknown })
const input = {}
console.log(Schema.decodeUnknownSync(schema)(input, { exact: true }))
/*
throws
ParseError: { readonly a: unknown }
└─ "a"
└─ is missing
*/
まあ、decode時のみの挙動なら許容かmrsekut.icon
encoding
Schema.encodeSync
失敗したらthrow error
Schema.encodeOption
Option型を返す
Schema.encodeEither
Either型を返す
Schema.encodePromise
encodeしてPromise返す
Schema.encode
encodeしてEffect返す
https://effect.website/docs/schema/getting-started/#handling-unsupported-encoding
eoncdeがサポートされていないschemaもある
Schema.decodeUnknownEither
Schema.transformOrFail
Schema.EitherFromSelf
Schema.typeSchema
ParseResult.succeed
ParseResult.fail
値にあって、Schemaにないpropertyは削除される
onExcessPropertyを使えば残すこともできる
encode時のエラーの取得
https://effect.website/docs/schema/getting-started/#receive-all-errors
propertyの順序を固定できる
https://effect.website/docs/schema/getting-started/#managing-property-order
いつ使う年mrsekut.icon
Schema.is
https://effect.website/docs/schema/getting-started/#type-guards
TypeScriptのTypeGuard
Schema.asserts
https://effect.website/docs/schema/getting-started/#assertions
Schema.asSchema
https://effect.website/docs/schema/basic-usage/#asschema
使い所がわからん
Schema.UniqueSymbolFromSelf
https://effect.website/docs/schema/basic-usage/#unique-symbols
code:ts
const mySymbol = Symbol.for("mySymbol")
const schema = Schema.UniqueSymbolFromSelf(mySymbol)
Schema.Literal
Schema.pickLiteral
https://effect.website/docs/schema/basic-usage/#the-pickliteral-utility
Pick<T, K extends keyof T>的なやつ
Schema.TemplateLiteral
Schema.TemplateLiteralParser
Schema.Union
Schema.NullOr
Schema.NullishOr
Schema.UndefinedOr
Schema.optionalWith
Schema.Tuple
https://effect.website/docs/schema/basic-usage/#tuples
Schema.optionalElement
Schema.Array
https://effect.website/docs/schema/basic-usage/#arrays
Schema.NonEmptyArray
Schema.Record
https://effect.website/docs/schema/basic-usage/#records
Readonly<T>と同じ意味になり、propertyはreadonlyになる
Schema.mutableを使うとmutableにできる
Schema.Struct
Schema.instanceOf
https://effect.website/docs/schema/basic-usage/#instanceof
.pick
https://effect.website/docs/schema/basic-usage/#picking
.omit
https://effect.website/docs/schema/basic-usage/#omitting
.partial
https://effect.website/docs/schema/basic-usage/#partial
.required
https://effect.website/docs/schema/basic-usage/#required
Schema.keyof
https://effect.website/docs/schema/basic-usage/#keyof
Schema.filter
Schema.typeSchema
https://effect.website/docs/schema/projections/#typeschema
変換処理などを取り除いて、SchemaのTypeだけ取り出す
Schema.encodedSchema
encode形式だけ取り出す
Schema.encodedBoundSchema
変換前の制約だけ残す
Schema.compose
Schema.filterと違って変換するやつかな
e.g.
code:ts
const Original = Schema.Struct({
foo: Schema.String.pipe(
Schema.minLength(3),
Schema.compose(Schema.Trim)
)
})
Schema.Trim
decode時に前後の空白を取り除く
Schema.declare
任意の型(この例では File)に対してスキーマを定義できる
code:ts
const FileFromSelf = Schema.declare(
(input: unknown): input is File => input instanceof File
)
declare の第一引数は 型ガード関数。
decodeUnknownSync を使うことで、そのスキーマに対して バリデーション + デコード ができます。
https://effect.website/docs/schema/advanced-usage/#primitive-data-types
型コンストラクタ
genericなSchemaも定義できる
https://effect.website/docs/schema/advanced-usage/#type-constructors
Arbitrary (effect)
https://effect.website/docs/schema/advanced-usage/#adding-compilers-annotations
QuickCheck風のランダムデータ生成(Arbitrary)には、追加のアノテーションが必要です:
code:ts
arbitrary: () => (fc) =>
fc.tuple(fc.string(), fc.string()).map((content, path) => new File(content, path))
これにより FastCheck.sample を使ってテスト用のデータを生成できます。
Schema.PropertySignature
「外部のデータ構造」から「内部の型」への変換ルールを表現するもの
https://effect.website/docs/schema/advanced-usage/#property-signatures
code:ts
import { Schema } from "effect"
const Person = Schema.Struct({
name: Schema.String,
age: Schema.propertySignature(Schema.NumberFromString).annotations({
title: "Age" // Annotation to label the age field
})
})
これは "age" フィールドが string(例: "18")として与えられても、内部的には number として扱えるようにするスキーマを定義しています。
jotai-decode-formとかでやりたかったのと同じ話だmrsekut.icon
🔍 PropertySignature の型パラメータ
code:_
PropertySignature<ToToken, ToType, FromKey, FromToken, FromType, HasDefault, Context>
それぞれの意味は:
table:_
パラメータ 意味
ToToken 内部型(出力)での : or ?:(必須かオプショナルか)
ToType 出力時の型(例: number)
FromKey 入力側のフィールド名。省略時はToと同じ
FromToken 入力側の : or ?:(必須かオプショナルか)
FromType 入力時の型(例: string)
HasDefault デフォルト値があるか(true or false)
Context 注釈やメタ情報など(通常 never)
例:
code:ts
age: PropertySignature<":", number, never, ":", string, false, never>
これは次のように読み取れます:
age フィールドは必須(:)
出力は number
入力も必須(:)
入力は string
デフォルト値なし
🔁 フィールド名のマッピング(fromKey)
外部データのキー名が異なる場合には、Schema.fromKey を使います。
code:ts
const Person = Schema.Struct({
age: Schema.propertySignature(Schema.NumberFromString).pipe(
Schema.fromKey("AGE")
)
})
この例では "AGE" というキーを内部の age にマッピングしています。
Schema.optional
schema
Introduction
Getting Started
Basic Usage
Filters
Advanced Usage
Projections
Transformations
https://effect.website/docs/schema/transformations/
Schema.transform
Schema.transformOrFail
Schema.compose
Annotations
https://effect.website/docs/schema/annotations/
説明つけるやつ
Error Messages
https://effect.website/docs/schema/error-messages/
Error Formatters
https://effect.website/docs/schema/error-formatters/
エラーを見やすっく
Class APIs
Schema.Class
Default Constructors
Schema.brand
https://effect.website/docs/schema/default-constructors/
Effect Data Types
https://effect.website/docs/schema/effect-data-types/
クソ長い
Overview
Interop With Data
Config
Option (effect)
Option
OptionFromSelf
OptionFromUndefinedOr
OptionFromNullOr
OptionFromNullishOr
OptionFromNonEmptyTrimmedString
Either (effect)
Either
EitherFromSelf
EitherFromUnion
Exit
Exit
Handling Defects in Serialization
ExitFromSelf
ReadonlySet
ReadonlySet
ReadonlySetFromSelf
Schema.ReadonlyMap
Schema.HashSet
HashSet
HashSetFromSelf
Schema.HashMap
SortedSet
SortedSet
SortedSetFromSelf
Duration
Duration
DurationFromSelf
DurationFromMillis
DurationFromNanos
clampDuration
Redacted
Redacted
RedactedFromSelf
Standard Schema
Standard Schemaに変換
Schema.standardSchemaV1
https://effect.website/docs/schema/standard-schema/
Arbitrary (effect)
fast-check向けのやつ
https://effect.website/docs/schema/arbitrary/
JSON Schema
https://effect.website/docs/schema/json-schema/
Equivalence
Schema.equivalenceで同値性を確認できる
https://effect.website/docs/schema/equivalence/
Pretty Printer
https://effect.website/docs/schema/pretty/